# Code Dumps
import math
from math import degrees, radians

import pyglet
from pyglet.gl import  *
from pyglet.window import key

import cocos
from cocos.actions import *
from cocos.layer import *
from cocos.scene import *
from cocos.director import director
from cocos.scenes.transitions import *
from cocos.sprite import Sprite
from cocos.particle import *
from cocos.particle_systems import *

import Box2D as box2d

from res import Images

class PlayerBox1(Sprite):
    "The box guy the player plays"
    TOP_BOOSTPTS = 255
    BOOSTPTS_DECREASE = 1.0*TOP_BOOSTPTS
    BOOSTPTS_INCREASE = 0.05*TOP_BOOSTPTS
    def __init__(self, world, *args, **kwargs):
        "setup sprite, keys"
        super(PlayerBox,self).__init__(Images.box, *args, **kwargs)
        self.world = world
        self.keys = key.KeyStateHandler()
        director.window.push_handlers(self.keys)
        
        self.boxBlur = self.BoxBlur(box=self)
        self.velocityVec = box2d.b2Vec2(0,0) # connected to analog stick
        
        self.moveSpeed = 100.0*0.001
        self.boostSpeed = self.moveSpeed * 300
        
        self.boosting = False
        self.boostPts = self.TOP_BOOSTPTS
        
        self.moveColor = (100,255,50)
        self.boostColor = (0,255,255)
        
        self.color = self.moveColor
        #self.jumpSpeed = 1.0
        
        "BodyDef"
        self.bodyDef = box2d.b2BodyDef()
        self.bodyDef.linearDamping = 1
        self.bodyDef.angularDamping = 0.6
        
        "Box ShapeDef"
        self.boxShapeDef = box2d.b2PolygonDef()
        self.boxShapeDef.SetAsBox(
                          self.width/self.world.RATIO/2.0, 
                         self.height/self.world.RATIO/2.0, 
                         (0,0), 0)
        self.boxShapeDef.density = 1.0
        self.boxShapeDef.friction = 0.3
        self.boxShapeDef.restitution = 0.6
        
        "Feet ShapeDef"
        #self.feetShapeDef = box2d.b2PolygonDef()
        #self.feetShapeDef.SetAsBox(
        #                    self.width/self.world.RATIO/2.0, 
        #                     0.1/self.world.RATIO,
        #                     (0,-(self.height/self.world.RATIO/2.)),0)
        #self.feetShapeDef.density = 2.0
        #self.feetShapeDef.friction = 0.5
        #self.feetShapeDef.restitution = 0.6
        #self.feetShapeDef.isSensor = True
    
        "Create the body and the shape(s)"
        self.body = self.world.CreateBody(self.bodyDef)
        self.body.SetBullet(True)
        self.boxShape = self.body.CreateShape(self.boxShapeDef)
        #self.feetShape= self.body.CreateShape(self.feetShapeDef)
        self.body.SetMassFromShapes()
        
        
    def update(self,dt):
        self.boxBlur.update(dt)
        self.move(dt)
        if self.keys[key.SPACE]:
            self.boosting = True
            self.boost(dt)
        if not self.keys[key.SPACE]:
            self.boosting = False
            self.rechargeBoost(dt)

        

        "Update the sprite pos and rot based on its b2Body"
        self.position = (self.body.position * self.world.RATIO).tuple()
        self.rotation = -(degrees(self.body.angle))
        
    def move(self,dt=0):
        self.color = self.moveColor
        self.scale = 1.0
        self.body.WakeUp()
        self.body.ApplyImpulse((-self.velocityVec * self.moveSpeed), self.body.position)
        
    def boost(self,dt=0):
        if self.boostPts <= 0:
            self.color = self.moveColor
            self.scale = 1.0
            self.boosting = False
            return
        self.color = self.boostColor
        self.scale = 1.25
        self.body.WakeUp()
        self.body.ApplyImpulse((-self.velocityVec * self.boostSpeed), self.body.position)
        self.boostPts -= self.BOOSTPTS_DECREASE
        
    def rechargeBoost(self,dt=0):
        if self.boostPts < self.TOP_BOOSTPTS:
            self.boostPts += self.BOOSTPTS_INCREASE
        
    
        
    def isOnGround(self):
        "Is my feet standing on a ground?"
        #shape_pairs = [(p.shape1, p.shape2) for p in self.world.points]
        #for shape1, shape2 in shape_pairs:
        #    if (shape1 == self.feetShape) or (shape2 == self.feetShape):
        #        return True
        return False
    
    class BoxBlur(Layer):
        "Box motion blur"

        def __init__(self, box):
            Layer.__init__(self)
            self.box = box
            #self.anchor = self.box.anchor
            self.active = False
            self.moveBlur = False
            self.boostBlur = False
            
        def update(self,dt):
            self.active = True if self.box.velocityVec.tuple() != box2d.b2Vec2_zero.tuple() else False 
            #print pyglet.clock._default._schedule_interval_items
            if self.active:
                if self.box.boosting:
                    if self.moveBlur:
                        self.unschedule(self.addMoveBlur)
                        self.moveBlur = False
                    if not self.boostBlur:
                        self.schedule_interval(self.addBoostBlur, 1/1000.)
                        self.boostBlur = True  
                elif not self.box.boosting:
                    if self.boostBlur:
                        self.unschedule(self.addBoostBlur)
                        self.boostBlur = False
                    if not self.moveBlur:
                        self.schedule_interval(self.addMoveBlur, 1/500.)
                        self.moveBlur = True
            
            elif not self.active:
                self.moveBlur = self.boostBlur = False 
                self.unschedule(self.addMoveBlur)
                self.unschedule(self.addBoostBlur)

        def addMoveBlur(self,dt):
            
            blur = Sprite(Images.box,opacity=200)
            blur._group = pyglet.sprite.SpriteGroup(blur._texture, GL_SRC_ALPHA, GL_ONE, None)
            blur._create_vertex_list()
            blur.position = self.box.position
            blur.rotation = self.box.rotation
            blur.color = self.box.moveColor 
            blur.scale=self.box.scale 
            self.add(blur)
            
            blur.do(FadeOut(1.0) + self.RemoveBlur())
        
        def addBoostBlur(self,dt):
            blur = Sprite(Images.box,opacity=200)
            blur._group = pyglet.sprite.SpriteGroup(blur._texture, GL_SRC_ALPHA, GL_ONE, None)
            blur._create_vertex_list()
            blur.position = self.box.position
            blur.rotation = self.box.rotation
            blur.color = self.box.boostColor 
            blur.scale=self.box.scale 
            self.add(blur)
            blur.do(FadeOut(1.0) + self.RemoveBlur())
                #blur._usage = "dynamic"
                #pyglet.sprite.Sprite.__init__(blur, Images.box, blend_src=GL_SRC_ALPHA, blend_dest=GL_ONE)
            
                
        class RemoveBlur( InstantAction ):
            def init(self):
                pass
            def start(self):
                self.target.parent.remove(self.target)
           
            #self.gravity = Point2(self.box.velocityVec.x * 1, self.box.velocityVec.y * 1)
            #self.angle = 90
        
class PlayerBox2(Sprite):
    "The box guy the player plays"
    TOP_BOOSTPTS = 255
    BOOSTPTS_DECREASE = 1.0*TOP_BOOSTPTS
    BOOSTPTS_INCREASE = 0.05*TOP_BOOSTPTS
    def __init__(self, world, *args, **kwargs):
        "setup sprite, keys"
        super(PlayerBox,self).__init__(Images.box, *args, **kwargs)
        self.world = world
        self.keys = key.KeyStateHandler()
        director.window.push_handlers(self.keys)
        
        "State"
        self.state = "alive"
        
        
        "HP - hit points"
        self.hp = 100
        
        "Vector"
        self.velocityVec = box2d.b2Vec2(0,0) # connected to analog stick
        self.weaponVec = box2d.b2Vec2(0,0)
        self.weaponAngle = 0
        
        "BodyDef"
        self.bodyDef = box2d.b2BodyDef()
        self.bodyDef.linearDamping = 1
        self.bodyDef.angularDamping = 0.6
        
        "Box ShapeDef"
        self.boxShapeDef = box2d.b2PolygonDef()
        self.boxShapeDef.SetAsBox(
                          self.width/self.world.RATIO/2.0, 
                         self.height/self.world.RATIO/2.0, 
                         (0,0), 0)
        self.boxShapeDef.density = 1.0
        self.boxShapeDef.friction = 0.3
        self.boxShapeDef.restitution = 0.6

        "Create the body and the shape(s)"
        self.body = self.world.CreateBody(self.bodyDef)
        self.body.SetBullet(True)
        self.boxShape = self.body.CreateShape(self.boxShapeDef)
        self.body.SetMassFromShapes()
        
        "Box Blur"
        self.boxBlur = self.BoxBlur(box=self)        
        self.boosting = False
        self.boostPts = self.TOP_BOOSTPTS
        self.moveSpeed = 100.0*0.001
        self.moveColor = (100,255,50)
        
        self.color = self.moveColor
        
        "Weapons"
        self.weapons = {}
        self.activeWeapon = None

        self.addWeapon(weapon.SemiAutoRifle(self.world, self), "semiAutoRifle")
        self.addWeapon(weapon.NoWeapon(self.world, self), "noWeapon")
        #self.addWeapon(weapon.Kunai(self.world, self), "kunai")
        self.setActiveWeapon("semiAutoRifle")
        

    def update(self,dt):
        self.boxBlur.update(dt)
        
        if self.state == "alive":
            self.move(dt)
            self.changeWeapon(dt)
            self.dropWeapon(dt)
            self.throwWeapon(dt)
            
            if self.keys[key.BACKSPACE]:
                self.hp -=10

            "Update the sprite pos and rot based on its b2Body"
            self.position = (self.body.position * self.world.RATIO).tuple()
            self.rotation = -(degrees(self.body.angle))
    
    def move(self,dt=0):
        "Mooove"
        self.body.WakeUp()
        #self.body.ApplyImpulse((-self.velocityVec * self.moveSpeed), self.body.position)
        
        if self.keys[key.W]:
            self.velocityVec = -box2d.b2Vec2(0,46)
        if self.keys[key.A]:
            self.velocityVec = -box2d.b2Vec2(-46,0)
        if self.keys[key.S]:
            self.velocityVec = -box2d.b2Vec2(0,-46)
        if self.keys[key.D]:
            self.velocityVec = -box2d.b2Vec2(46,0)
        
        if self.keys[key.W] and self.keys[key.D]:
            self.velocityVec = -box2d.b2Vec2(33,33)
        if self.keys[key.D] and self.keys[key.S]:
            self.velocityVec = -box2d.b2Vec2(33,-33)
        if self.keys[key.S] and self.keys[key.A]:
            self.velocityVec = -box2d.b2Vec2(-33,-33)
        if self.keys[key.A] and self.keys[key.W]:
            self.velocityVec = -box2d.b2Vec2(-33,33)
        if (not self.keys[key.A] and not self.keys[key.W] and not self.keys[key.S] and not self.keys[key.D]):
            self.velocityVec = box2d.b2Vec2(0,0)
        
        self.body.ApplyImpulse((-self.velocityVec * self.moveSpeed), self.body.position)
        #self.velocityVec = box2d.b2Vec2(0,0)
     
    def setActiveWeapon(self,str):
        "Use one of the available weapons"
        if str not in self.weapons.keys():
            return
        if self.activeWeapon == self.weapons[str]:
            return 
        if self.activeWeapon:
            self.world.remove(self.activeWeapon)
            self.activeWeapon.setActive(False)
        self.activeWeapon = self.weapons[str]
        self.activeWeapon.setActive(True)
        self.world.add(self.activeWeapon)
       
    def changeWeapon(self,dt):
        "Change active weapon to other available ones"
        if self.keys[key._1]:
            self.setActiveWeapon("semiAutoRifle")
        elif self.keys[key._2]:
            self.setActiveWeapon("kunai")
            
    def dropWeapon(self,dt):
        "Drop current weapon"
        if self.keys[key.BACKSLASH]:
            if self.activeWeapon != self.weapons["noWeapon"]:
                self.activeWeapon.drop(dt)
                self.removeWeapon([k for k, v in self.weapons.iteritems() if v == self.activeWeapon][0])
                
    def throwWeapon(self,dt=0):
        "Throw current weapon to something else"
        if self.keys[key.SLASH]:
            if self.activeWeapon != self.weapons["noWeapon"]:
        
                self.activeWeapon.throw(dt)
                self.removeWeapon([k for k, v in self.weapons.iteritems() if v == self.activeWeapon][0])
            
    
    def addWeapon(self,w,name):
        "Add a weapon"
        self.weapons[name] = w
        w.box = self
        w.state = "held"
        if isinstance(self.activeWeapon, weapon.NoWeapon):
            self.setActiveWeapon(name)
        
            
    def removeWeapon(self,name):
        "Remove available weapon"    
        self.activeWeapon = None
        del self.weapons[name]
        if "semiAutoRifle" in self.weapons.keys():
            self.box.setActiveWeapon("semiAutoRifle")
        else:
            self.setActiveWeapon("noWeapon")
        
    def onTriggerWeapon(self,dt):
        "Triggered"
        self.activeWeapon.onTrigger(dt)
    
    def offTriggerWeapon(self,dt):
        "Relased Trigger"
        self.activeWeapon.offTrigger(dt)

    class CrossHair(Sprite):
        def __init__(self, world, *args, **kwargs):
            "setup sprite, keys"
            super(PlayerBox,self).__init__(Images.box, *args, **kwargs)
            self.world = world
                

    class BoxBlur(Layer):
        "Box motion blur"

        def __init__(self, box):
            Layer.__init__(self)
            self.box = box
            #self.anchor = self.box.anchor
            self.active = False
            self.moveBlur = False
            self.limit = 8
            
        def update(self,dt):
            pass
        class RemoveBlur( InstantAction ):
            def init(self):
                pass
            def start(self):
                self.target.parent.remove(self.target)
           
